//
//  DMConfigManager.m
//  DualMediationSDK
//
//  配置管理器实现
//

#import "DMConfigManager.h"
#import "../Utils/Logger/IMLogUtils.h"
#import "../Utils/Network/IMNetworkUtils.h"
#import "../Utils/JSON/IMJSONUtils.h"

@interface DMConfigManager ()

@property (nonatomic, strong) DMAdConfig *currentAdConfig;
@property (nonatomic, strong) NSDictionary *remoteConfigData;
@property (nonatomic, assign) BOOL isInitialized;
@property (nonatomic, strong) NSTimer *refreshTimer;
@property (nonatomic, strong) dispatch_queue_t configQueue;
@property (nonatomic, strong) NSURL *remoteConfigURL;

@end

@implementation DMConfigManager

#pragma mark - Singleton

static DMConfigManager *_sharedManager = nil;
static dispatch_once_t onceToken;

+ (instancetype)sharedManager {
    dispatch_once(&onceToken, ^{
        _sharedManager = [[self alloc] init];
    });
    return _sharedManager;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _configQueue = dispatch_queue_create("com.dualmediation.config.queue", DISPATCH_QUEUE_SERIAL);
        [IMLogUtils info:IMLogTagSDKInit format:@"DMConfigManager created."];
    }
    return self;
}

- (void)dealloc {
    [IMLogUtils debug:IMLogTagGeneral format:@"DMConfigManager deallocating..."];
    [self setAutoUpdateEnabled:NO interval:0];
}

#pragma mark - Initialization

- (void)initializeWithConfig:(DMAdConfig *)config
                  completion:(void(^)(BOOL success, NSError * _Nullable error))completion {
    
    [IMLogUtils info:IMLogTagSDKInit format:@"DMConfigManager initializing with config..."];
    
    dispatch_async(_configQueue, ^{
        if (self.isInitialized) {
            [IMLogUtils warning:IMLogTagSDKInit format:@"DMConfigManager already initialized"];
            if (completion) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    completion(YES, nil);
                });
            }
            return;
        }
        
        self.currentAdConfig = config;
        [IMLogUtils info:IMLogTagSDKInit format:@"Loaded initial config with %lu ad units", (unsigned long)config.adUnitIds.count];
        
        // 尝试获取远程配置
        [self fetchRemoteConfig:^(BOOL success, DMConfigUpdateType updateType, NSError *error) {
            if (success) {
                [IMLogUtils info:IMLogTagSDKInit format:@"Remote config fetched successfully"];
            } else {
                [IMLogUtils warning:IMLogTagSDKInit format:@"Remote config fetch failed, using local config: %@", error.localizedDescription];
            }
            
            self.isInitialized = YES;
            [IMLogUtils info:IMLogTagSDKInit format:@"DMConfigManager initialization completed"];
            
            if (completion) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    completion(YES, nil);
                });
            }
        }];
    });
}

#pragma mark - Configuration Access

- (DMAdConfig *)getCurrentConfig {
    [IMLogUtils verbose:IMLogTagGeneral format:@"Retrieving current config"];
    __block DMAdConfig *config = nil;
    dispatch_sync(_configQueue, ^{
        config = self.currentAdConfig;
    });
    return config;
}

- (nullable NSDictionary *)getPlacementConfig:(NSString *)placementId {
    [IMLogUtils debug:IMLogTagGeneral format:@"Getting placement config for ID: %@", placementId];
    
    NSString *adUnitId = [self getAdUnitIdForPlacement:placementId];
    if (adUnitId) {
        [IMLogUtils verbose:IMLogTagGeneral format:@"Found placement config for ID: %@", placementId];
        return @{
            @"adUnitId": adUnitId,
            @"placementId": placementId,
            @"platformConfigs": self.currentAdConfig.platformConfigs ?: @{}
        };
    }
    
    [IMLogUtils warning:IMLogTagGeneral format:@"Placement config not found for ID: %@", placementId];
    return nil;
}

- (nullable NSString *)getAdUnitIdForPlacement:(NSString *)placementId {
    if (!placementId) {
        [IMLogUtils warning:IMLogTagGeneral format:@"Placement ID is nil"];
        return nil;
    }
    
    __block NSString *foundAdUnitId = nil;
    dispatch_sync(_configQueue, ^{
        // 在adUnitIds字典中查找对应的广告单元ID
        foundAdUnitId = self.currentAdConfig.adUnitIds[placementId];
    });
    
    if (foundAdUnitId) {
        [IMLogUtils verbose:IMLogTagGeneral format:@"AdUnit ID found for placement %@: %@", placementId, foundAdUnitId];
    } else {
        [IMLogUtils warning:IMLogTagGeneral format:@"AdUnit ID not found for placement: %@", placementId];
    }
    
    return foundAdUnitId;
}

- (nullable NSString *)getAdUnitForId:(NSString *)adUnitId {
    if (!adUnitId) {
        [IMLogUtils warning:IMLogTagGeneral format:@"AdUnit ID is nil"];
        return nil;
    }
    
    __block NSString *foundAdUnitId = nil;
    dispatch_sync(_configQueue, ^{
        // 检查是否存在该adUnitId
        for (NSString *key in self.currentAdConfig.adUnitIds.allKeys) {
            if ([self.currentAdConfig.adUnitIds[key] isEqualToString:adUnitId]) {
                foundAdUnitId = self.currentAdConfig.adUnitIds[key];
                break;
            }
        }
    });
    
    if (foundAdUnitId) {
        [IMLogUtils verbose:IMLogTagGeneral format:@"AdUnit found: %@", adUnitId];
    } else {
        [IMLogUtils warning:IMLogTagGeneral format:@"AdUnit not found: %@", adUnitId];
    }
    
    return foundAdUnitId;
}

#pragma mark - Remote Configuration

- (void)setRemoteConfigURL:(NSURL *)url {
    [IMLogUtils info:IMLogTagGeneral format:@"Setting remote config URL: %@", url.absoluteString];
    dispatch_async(_configQueue, ^{
        self.remoteConfigURL = url;
    });
}

- (void)fetchRemoteConfig:(void(^)(BOOL success, DMConfigUpdateType updateType, NSError * _Nullable error))completion {
    [IMLogUtils info:IMLogTagNetwork format:@"Starting remote config fetch"];
    
    dispatch_async(_configQueue, ^{
        if (!self.remoteConfigURL) {
            [IMLogUtils warning:IMLogTagNetwork format:@"Remote config URL not set"];
            if (completion) {
                NSError *error = [NSError errorWithDomain:@"DMConfigManager" code:1001 userInfo:@{NSLocalizedDescriptionKey: @"Remote config URL not set"}];
                dispatch_async(dispatch_get_main_queue(), ^{
                    completion(NO, DMConfigUpdateTypeRemote, error);
                });
            }
            return;
        }
        
        [IMLogUtils debug:IMLogTagNetwork format:@"Fetching from URL: %@", self.remoteConfigURL.absoluteString];
        
        [IMNetworkUtils GET:self.remoteConfigURL.absoluteString
                 parameters:@{@"version": @"1.0"}
                    success:^(IMNetworkResponse *response) {
                        [IMLogUtils info:IMLogTagNetwork format:@"Remote config response received, status: %ld", (long)response.statusCode];
                        [self handleRemoteConfigResponse:response completion:completion];
                    }
                    failure:^(IMNetworkResponse *response) {
                        [IMLogUtils error:IMLogTagNetwork format:@"Remote config fetch failed: %@", response.error.localizedDescription];
                        if (completion) {
                            dispatch_async(dispatch_get_main_queue(), ^{
                                completion(NO, DMConfigUpdateTypeRemote, response.error);
                            });
                        }
                    }];
    });
}

- (void)handleRemoteConfigResponse:(IMNetworkResponse *)response completion:(void(^)(BOOL, DMConfigUpdateType, NSError *))completion {
    [IMLogUtils debug:IMLogTagGeneral format:@"Processing remote config response"];
    
    if (![response.data isKindOfClass:[NSDictionary class]]) {
        [IMLogUtils error:IMLogTagGeneral format:@"Invalid remote config format"];
        if (completion) {
            NSError *error = [NSError errorWithDomain:@"DMConfigManager" code:1002 userInfo:@{NSLocalizedDescriptionKey: @"Invalid config format"}];
            dispatch_async(dispatch_get_main_queue(), ^{
                completion(NO, DMConfigUpdateTypeRemote, error);
            });
        }
        return;
    }
    
    NSDictionary *remoteData = (NSDictionary *)response.data;
    [IMLogUtils info:IMLogTagGeneral format:@"Remote config contains keys: %@", remoteData.allKeys];
    
    self.remoteConfigData = remoteData;
    [self mergeRemoteConfigWithLocal:remoteData];
    
    [IMLogUtils info:IMLogTagGeneral format:@"Remote config merged successfully"];
    
    if (completion) {
        dispatch_async(dispatch_get_main_queue(), ^{
            completion(YES, DMConfigUpdateTypeMerged, nil);
        });
    }
}

- (void)mergeRemoteConfigWithLocal:(NSDictionary *)remoteConfig {
    [IMLogUtils debug:IMLogTagGeneral format:@"Merging remote config with local"];
    
    // 合并广告单元配置
    NSDictionary *remoteAdUnits = remoteConfig[@"ad_unit_ids"];
    if ([remoteAdUnits isKindOfClass:[NSDictionary class]]) {
        [IMLogUtils info:IMLogTagGeneral format:@"Merging %lu remote ad unit IDs", (unsigned long)remoteAdUnits.count];
        
        // 合并到现有的adUnitIds中
        NSMutableDictionary *mergedAdUnitIds = [self.currentAdConfig.adUnitIds mutableCopy] ?: [NSMutableDictionary dictionary];
        [mergedAdUnitIds addEntriesFromDictionary:remoteAdUnits];
        self.currentAdConfig.adUnitIds = [mergedAdUnitIds copy];
        
        [IMLogUtils debug:IMLogTagGeneral format:@"Updated adUnitIds count: %lu", (unsigned long)self.currentAdConfig.adUnitIds.count];
    }
    
    // 合并平台配置
    NSDictionary *platformConfigs = remoteConfig[@"platform_configs"];
    if ([platformConfigs isKindOfClass:[NSDictionary class]]) {
        [IMLogUtils info:IMLogTagGeneral format:@"Merging platform configurations"];
        
        NSMutableDictionary *mergedPlatformConfigs = [self.currentAdConfig.platformConfigs mutableCopy] ?: [NSMutableDictionary dictionary];
        [mergedPlatformConfigs addEntriesFromDictionary:platformConfigs];
        self.currentAdConfig.platformConfigs = [mergedPlatformConfigs copy];
        
        [IMLogUtils debug:IMLogTagGeneral format:@"Updated platform configs count: %lu", (unsigned long)self.currentAdConfig.platformConfigs.count];
    }
    
    // 合并启用的平台列表
    NSArray *enabledPlatforms = remoteConfig[@"enabled_platforms"];
    if ([enabledPlatforms isKindOfClass:[NSArray class]]) {
        [IMLogUtils info:IMLogTagGeneral format:@"Updating enabled platforms list"];
        self.currentAdConfig.enabledPlatforms = enabledPlatforms;
        [IMLogUtils debug:IMLogTagGeneral format:@"Enabled platforms: %@", [enabledPlatforms componentsJoinedByString:@", "]];
    }
    
    // 合并测试设备ID
    NSArray *testDeviceIds = remoteConfig[@"test_device_ids"];
    if ([testDeviceIds isKindOfClass:[NSArray class]]) {
        [IMLogUtils info:IMLogTagGeneral format:@"Updating test device IDs"];
        self.currentAdConfig.testDeviceIds = testDeviceIds;
    }
    
    // 合并合规设置
    NSNumber *gdprEnabled = remoteConfig[@"gdpr_enabled"];
    if ([gdprEnabled isKindOfClass:[NSNumber class]]) {
        self.currentAdConfig.gdprEnabled = [gdprEnabled boolValue];
        [IMLogUtils debug:IMLogTagGeneral format:@"GDPR enabled: %@", self.currentAdConfig.gdprEnabled ? @"YES" : @"NO"];
    }
    
    NSNumber *ccpaEnabled = remoteConfig[@"ccpa_enabled"];
    if ([ccpaEnabled isKindOfClass:[NSNumber class]]) {
        self.currentAdConfig.ccpaEnabled = [ccpaEnabled boolValue];
        [IMLogUtils debug:IMLogTagGeneral format:@"CCPA enabled: %@", self.currentAdConfig.ccpaEnabled ? @"YES" : @"NO"];
    }
    
    [IMLogUtils debug:IMLogTagGeneral format:@"Config merge completed"];
}

#pragma mark - Auto Update

- (void)setAutoUpdateEnabled:(BOOL)enabled interval:(NSTimeInterval)interval {
    [IMLogUtils info:IMLogTagGeneral format:@"Setting auto update: %@ (interval: %.1fs)", enabled ? @"enabled" : @"disabled", interval];
    
    dispatch_async(_configQueue, ^{
        if (enabled) {
            [self startAutoUpdateWithInterval:interval];
        } else {
            [self stopAutoUpdate];
        }
    });
}

- (void)startAutoUpdateWithInterval:(NSTimeInterval)interval {
    [self stopAutoUpdate];
    
    [IMLogUtils debug:IMLogTagGeneral format:@"Starting auto update timer with interval: %.1fs", interval];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        self.refreshTimer = [NSTimer scheduledTimerWithTimeInterval:interval
                                                             target:self
                                                           selector:@selector(performAutoUpdate)
                                                           userInfo:nil
                                                            repeats:YES];
    });
}

- (void)stopAutoUpdate {
    if (self.refreshTimer) {
        [IMLogUtils debug:IMLogTagGeneral format:@"Stopping auto update timer"];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.refreshTimer invalidate];
            self.refreshTimer = nil;
        });
    }
}

- (void)performAutoUpdate {
    [IMLogUtils debug:IMLogTagGeneral format:@"Performing scheduled config update"];
    [self fetchRemoteConfig:nil];
}

#pragma mark - Missing Methods Implementation

- (BOOL)validateConfig:(NSDictionary *)config error:(NSError **)error {
    [IMLogUtils debug:IMLogTagGeneral format:@"Validating configuration"];
    
    if (!config || ![config isKindOfClass:[NSDictionary class]]) {
        if (error) {
            *error = [NSError errorWithDomain:@"DMConfigManager" 
                                         code:2001 
                                     userInfo:@{NSLocalizedDescriptionKey: @"Config must be a valid NSDictionary"}];
        }
        return NO;
    }
    
    // 基本验证规则
    NSArray *requiredKeys = @[@"adUnitIds", @"platformConfigs"];
    for (NSString *key in requiredKeys) {
        if (!config[key]) {
            if (error) {
                *error = [NSError errorWithDomain:@"DMConfigManager" 
                                             code:2002 
                                         userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Missing required key: %@", key]}];
            }
            return NO;
        }
    }
    
    [IMLogUtils debug:IMLogTagGeneral format:@"Configuration validation passed"];
    return YES;
}

- (NSDictionary *)getConfigValidationRules {
    [IMLogUtils debug:IMLogTagGeneral format:@"Getting configuration validation rules"];
    
    return @{
        @"required_keys": @[@"adUnitIds", @"platformConfigs"],
        @"optional_keys": @[@"debugMode", @"refreshInterval", @"fallbackConfig"],
        @"type_validation": @{
            @"adUnitIds": @"NSDictionary",
            @"platformConfigs": @"NSDictionary",
            @"debugMode": @"NSNumber",
            @"refreshInterval": @"NSNumber"
        },
        @"value_constraints": @{
            @"refreshInterval": @{@"min": @30, @"max": @3600}
        }
    };
}

@end 
